//
// Created by tacom on 2022/8/30.
//

#include "iostream"
#include "cuda_runtime.h"
#include "assert.h"

#define N 1000

__global__ void vector_add(float *a, float *b, float *c, int n){
    int index = blockIdx.x * blockDim.x + threadIdx.x;
    if (index < n){
        c[index] = a[index] + b[index];
    }
}


int main(){
    const size_t size = N * sizeof (float );
    float *h_a = (float *) malloc(size);
    float *h_b = (float *) malloc(size);
    float *h_c = (float *) malloc(size);

    for (int i = 0; i < N; ++i){
        h_a[i] = rand() / (float)RAND_MAX;
        h_b[i] = rand() / (float)RAND_MAX;
    }

    float *d_a, *d_b, *d_c;
    cudaMalloc((void **)&d_a, size);
    cudaMalloc((void **)&d_b, size);
    cudaMalloc((void **)&d_c, size);

    cudaMemcpy(d_a, h_a, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, h_b, size, cudaMemcpyHostToDevice);

    int threadNum = 256;
    int blockNum = (N + threadNum - 1) / threadNum;
    vector_add<<<blockNum, threadNum>>>(d_a, d_b, d_c, N);

    cudaMemcpy(h_c, d_c, size, cudaMemcpyDeviceToHost);
    for(int i = 0; i < N; ++i){
        assert(h_a[i] + h_b[i] == h_c[i]);
    }

    free(h_a);
    free(h_b);
    free(h_c);
    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);
}
